#!/usr/bin
# -*- coding: utf-8 -*-

import mod_parameters as params
import mod_node as nd
import mod_section as sec
import mod_material as mat



TCI = params.PARAMS["testConstructorsInputs"]
FLOAT = params.PARAMS["float"]



# ==============================================================================
class Element3D():
    ALLOWED_SECTIONS = None
    N_NODES = None
    TYPE = None

    def __init__(self, uId, nodes, section):
        if TCI:
            self.testInputs(uId, nodes, section)
        self.uId = uId
        self.nds = nodes
        self.sec = section

    def testInputs(self, uId, nodes, section):
        if not isinstance(uId, str):
            raise ValueError
        if not len(nodes) == self.N_NODES:
            raise ValueError
        for node in nodes:
            if not isinstance(node, nd.Node):
                raise ValueError
        if not isinstance(section, sec.Section):
            raise ValueError
        if not section.TYPE in self.ALLOWED_SECTIONS:
            raise ValueError

    def getNodesUserIds(self):
        a = []
        for nd in self.nds:
            a.append(nd.uId)
        return a

    def __str__(self):
        a = "Element " + self.TYPE + ":\n"
        a += "- user id: " + str(self.uId) + "\n"
        a += "- nodes user ids: " + str(self.getNodesUserIds()) + "\n"
        a += "- section: " + str(self.sec)
        return a



# ==============================================================================
class Q4Thick3D(Element3D):
    """ 4 nodes 3D space thick shell element
    """
    ALLOWED_SECTIONS = ("HomogeneousShellSection",)
    N_NODES = 4
    TYPE = "Q4Thick3D"

    def __init__(self, uId, nodes, section):
        Element3D.__init__(self, uId, nodes, section)

    def D(self):
        self.Dmat = npzeros((5, 5), dtype=FLOAT)

        if self.sec.mat.TYPE == "IsotropicElasticMaterial":
            E = self.sec.mat.params["E"]
            nu = self.sec.mat.params["nu"]
            a = E / (1.0 - nu ** 2)
            b = E / (1.0 + nu)

            self.Dmat[0, 0] = a
            self.Dmat[1, 1] = a
            self.Dmat[0, 1] = a * nu
            self.Dmat[1, 0] = a * nu
            self.Dmat[2, 2] = a * 0.5 * (1.0 - nu)
            self.Dmat[3, 3] = b
            self.Dmat[4, 4] = b

        else:
            raise ValueError, "The material must be in ..."



# ==============================================================================
class Q8Thick3D(Element3D):
    """ 8 nodes 3D space shell element
    """
    ALLOWED_SECTIONS = ("HomogeneousShellSection",)
    N_NODES = 8
    TYPE = "Q8Thick3D"

    def __init__(self, uId, nodes, section):
        Element3D.__init__(self, uId, nodes, section)



# ==============================================================================
if __name__ == "__main__":
    myMaterial = mat.IsotropicElasticMaterial("Aluminium", {"E":70000.0,
                                                            "nu":0.25})
    mySection = sec.HomogeneousShellSection("Plaque isotrope",
                                            {"thickness":2.0},
                                            myMaterial)
    myNode1 = nd.Node3D("n1", (0, 0, 0))
    myNode2 = nd.Node3D("n2", (1, 0, 0))
    myNode3 = nd.Node3D("n3", (1, 1, 0))
    myNode4 = nd.Node3D("n4", (0, 1, 0))

    myElement = Q4Thick3D("e1", (myNode1, myNode2,
                                 myNode3, myNode4), mySection)
    print myElement

